<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
    </style>
</head>

<body>
    <canvas id="canvas"></canvas>
</body>
<script id="VertexShader" type="x-shader/x-vertex">
    attribute vec4 a_Position;
    uniform float u_PointSize;
    uniform float u_Set;

    varying float v_Set;
    void main(){
        gl_Position = a_Position;
        gl_PointSize = u_PointSize + (u_PointSize * u_Set) / 2.0;
        v_Set = u_Set;
    }
</script>
<script id="RadianFragmentShader" type="x-shader/x-fragment">
    precision mediump float;

    uniform vec4 u_line_Color;
    uniform vec2 u_Angle;
    varying float v_Set;

    float pi = radians(180.0);

    float getCosJ(){
        vec2 c = vec2(gl_PointCoord);
        vec2 mo = c - vec2(0.5,0.5);
        float l = mo.x;
        float x = distance(c,vec2(0.5,0.5));
        float cosj = l / x;
        return cosj;
    }

    bool getAngle(float j1,float j2,float t){
        float cosj = getCosJ() * t;
        float a = 0.0;
        float b = 0.0;
        if(t > 0.0){
            if(j1 < j2){
                a = cos(min(j1, 180.0) * pi / 180.0);
                b = cos(min(j2, 180.0) * pi / 180.0);
                if(a >= cosj && cosj >= b){
                    return true;
                }
            }else{
                //逆开角(先不算)
                a = cos(min(j2, 180.0) * pi / 180.0);
                b = cos(min(j1, 180.0) * pi / 180.0);
                if(!(a >= cosj && cosj >= b)){
                    return true;
                }
            }
        }else{
            //负角
            if(j1 < j2){
                a = cos(max(j1 - 180.0, 0.0) * pi / 180.0);
                b = cos(max(min(j2 - 180.0, 180.0), 0.0) * pi / 180.0);
                if(a >= cosj && cosj >= b){
                    return true;
                }
            }else{
                //逆开角(先不算)
                a = cos(max(j2 - 180.0, 0.0) * pi / 180.0);
                b = cos(max(min(j1 - 180.0, 180.0), 0.0) * pi / 180.0);
                if(!(a >= cosj && cosj >= b)){
                    return true;
                }
            }
        }

        return false;
    }

    //获取弧线头部的圆心到圆心的距离
    // j:从[0.5,0.5]的角度 posiRadius:弧线半径 radius:画的圆的半径 diffRadius:扩散半径
    float getAngular(float j, float posiRadius){
        float x = posiRadius;
        float l = x * cos(j * pi / 180.0);
        float d = x * sin((360.0 - j) * pi / 180.0);

        vec2 c = vec2(l + 0.5, d + 0.5);
        float dist = distance(gl_PointCoord, c);
        return dist;
    }

    //画弧线
    bool drawAngle(
        float j1, float j2,
        float lineStart, float lineEnd,
        float lineDiff,
        vec4 color
    ){
        bool s = false;
        if(gl_PointCoord.y <= 0.5){
            s = getAngle(j1, j2, 1.0);
        }else{
            s = getAngle(j1, j2,-1.0);
        }
        if(s == true){
            float dist = distance(gl_PointCoord, vec2(0.5,0.5));
            if(dist <= lineStart && dist >= lineEnd){
                
                if(dist >= lineStart - lineDiff){
                    //外渐变
                    color.a *= 1.0 - (dist - (lineStart - lineDiff)) / (lineDiff);
                    gl_FragColor = color;
                    return false;
                }else if(dist <= lineEnd + lineDiff){
                    //内渐变
                    color.a *= (dist - lineEnd) / (lineDiff);
                    gl_FragColor = color;
                    return false;
                }else{
                    //实线
                    gl_FragColor = color;
                    return false;
                }
            }
        }
        return true;
    }

    bool drawAngular(
        float j1, float j2,
        float lineStart, float lineRadius, float lineDiff,
        vec4 color
    ){
        float dist = getAngular(j1, lineStart - lineRadius - lineDiff);
        if(dist < lineRadius + lineDiff){
            color.a *= 1.0 - (dist - lineRadius) / (lineDiff);
            gl_FragColor = color;
            return false;
        }

        dist = getAngular(j2, lineStart - lineRadius - lineDiff);
        if(dist < lineRadius + lineDiff){
            color.a *= 1.0 - (dist - lineRadius) / (lineDiff);
            gl_FragColor = color;
            return false;
        }
        return true;
    }

    float getJ2(float j1, float j2, float set){
        float offAngle = 0.5;
        float curJ2 = j2;
        if(set <= offAngle){
            if(j1 > curJ2){
                curJ2 += 360.0;
            }
            curJ2 = (curJ2 - j1) * (set / offAngle) + j1;
            if(curJ2 > 360.0){
                curJ2 -= 360.0;
            }
        }else{
            curJ2 = j2;
        }
        return curJ2;
    }

    float getJ1(float j1, float j2, float set){
        float offAngle = 0.5;
        if(set >= offAngle){
            float xnj2 = j2;
            if(xnj2 < j1){
                xnj2 += 360.0;
            }
            j1 = (xnj2 - j1) * ((set - offAngle) / (1.0 - offAngle)) + j1;

            if(j1 > 360.0){
                j1 -= 360.0;
            }
        }
        return j1;
    }

    uniform vec3 u_Line;

    void main(){
        float u_line_S = u_Line.x;
        float u_line_Dia = u_Line.y;//直径
        float u_line_Diff = u_Line.z;//扩散半径
        float u_line_E = u_line_S - u_line_Dia - u_line_Diff * 2.0;
        float set = v_Set;
 
        if(set >= 1.0){
            return;
        }

        float j1 = u_Angle.x;
        //计算角二
        float j2 = getJ2(j1, u_Angle.y, set);

        j1 = getJ1(j1, j2, set);

        j1 += set * 100.0;
        j2 += set * 100.0;
        if(j1 >= 360.0){
            j1 -= 360.0;
        }
        if(j2 >= 360.0){
            j2 -= 360.0;
        }
            

        //计算弧线
        if(drawAngle(j1, j2, u_line_S, u_line_E, u_line_Diff, u_line_Color) == true){
            //计算圆角
            drawAngular(j1, j2, u_line_S, u_line_Dia / 2.0, u_line_Diff, u_line_Color);
        }

        
        
    }
</script>
<script type="module">


    import { Matrix4, Vector3, Color, OrthographicCamera, PerspectiveCamera, Spherical } from '../js/three.module.js';
    import { CreateProgram, imgPromise } from '../js/Utils.js';
    import lib from '../js/ThreeLib.js';
    import CameraController from '../js/CameraController.js'
    import Poly from '../js/Poly4.js'
    import Control from '../js/Control.js'
    import Arc from '../js/Arc.js'


    import Geo from '../js/Poly2/Geo.js'
    import Mat from '../js/Poly2/Mat.js'
    import Obj3D from '../js/Poly2/Obj3D.js'
    import Scene from '../js/Poly2/Scene.js'




    //#region gl
    const canvas = document.getElementById("canvas");
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight - 4;

    const gl = canvas.getContext("webgl", { antialias: true, });

    // gl.enable(gl.DEPTH_TEST);//开始背景遮挡会频闪
    gl.enable(gl.BLEND);
    gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
    gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);//去图片描边
    //#endregion



    const scene = new Scene({ gl: gl });
    scene.regProgram('arc', {
        program: CreateProgram(gl,
            document.querySelector('#VertexShader').innerText,
            document.querySelector('#RadianFragmentShader').innerText),
        attribs: ['a_Position'],
        uniforms: [
            'u_Angle', 'u_Set',
            'u_PointSize',
            'u_Line', 'u_line_Color'
        ]
    })



    const arc = new Arc({
        gl: gl,
        program: 'arc',
        pointSize: 30,
    });
    const dataArr = [];



    canvas.addEventListener('pointerdown', function (event) {
        const { clientX, clientY } = event;

        const [x, y] = getViewPosi(clientX, clientY);

        let obj = arc.getElement(new Vector3(x, y, 0), 0.5);
        console.log(obj)
        scene.add(obj);
        dataArr.push({
            set: 0,
            s: 0.01,
            obj: obj,
        });
    });




    let kj = [0.0, 0.2];//开角动画
    (function ani() {

        for (let i = 0; i < dataArr.length; i++) {
            let { set, obj, s } = dataArr[i];

            if (set > 1) {
                //删除
                deleteData(i);
                i--;
                continue;
            }

            dataArr[i].set += s;

            obj.setUniform('u_Set', { value: dataArr[i].set });
        }



        scene.draw();
        requestAnimationFrame(ani);
    })();

    function deleteData(index) {
        let { obj } = dataArr[index];
        // console.log('删除了', objs.length, '个')
        scene.remove(obj);
        // console.log('剩余', scene.children.length, '个')
        dataArr.splice(index, 1);
    }


    function getViewPosi(x, y) {
        const [hx, hy] = [canvas.width / 2, canvas.height / 2];
        const [cx, cy] = [
            (x - hx) / hx,
            -(y - hy) / hy,
        ];
        return [cx, cy];
    }

    function draw() {
        scene.draw();
    }
</script>
</script>

</html>